/*
	日常工具类
		1.日期工具.
		2.字符串工具.
*/
package tool

import (
	"bytes"
	"crypto/md5"
	"crypto/rand"
	"encoding/base64"
	"encoding/hex"
	"errors"
	"io"
	"strings"
	"time"
)

const DateFormat = "2006-01-02"
const DateMonFormat = "2006-01"
const DateYearFormat = "2006"
const TimeFormat = "2006-01-02 15:04:05"

var WeekDict = map[string]int{"Sunday": 0, "Monday": 1, "Tuesday": 2, "Wedenesday": 3, "Thursday": 4, "Friday": 5, "Saturday": 6}

// tool 工具包
// 日期工具类

// NowTimeLong 取当前时间戳
func NowTimeLong() int64 {
	return time.Now().Unix() * 100
}

// 获取当前时间 返回格式:2016-01-01 12:00:12
func NowTimeStr() string {
	return time.Now().Format(TimeFormat)
}

// 获取当前时间 返回格式:2016-01-01 12:00:12
func NowMonStr() string {
	return time.Now().Format(DateMonFormat)
}

//  获取当前日期 格式:2016-01-01
func NowDayStr() string {
	return time.Now().Format(DateFormat)
}

//  获取当前日期 格式:2016-01-01
func NowYearStr() string {
	return time.Now().Format(DateYearFormat)
}

// 校验字符串是否正确的日期
func ValidDateStr(dateStr, dateFormat string) bool {
	//layout为日期格式
	// value 为日期
	loc, _ := time.LoadLocation("Local") //重要：获取时区
	_, err := time.ParseInLocation(dateFormat, dateStr, loc)
	return err == nil
}

// 取两个日期之间的所有日期
func GetAllDaysBetween(startDate, endDate string) ([]string, error) {
	if ValidDateStr(startDate, DateFormat) && ValidDateStr(endDate, DateFormat) {
		loc, _ := time.LoadLocation("Local") //重要：获取时区
		st, _ := time.ParseInLocation(DateFormat, startDate, loc)
		et, _ := time.ParseInLocation(DateFormat, endDate, loc)
		days := int(et.UTC().Truncate(24*time.Hour).Sub(st.UTC().Truncate(24*time.Hour)).Hours() / 24)
		forDays := make([]string, days+1)
		for index := 0; index <= days; index++ {
			forDays[index] = et.AddDate(0, 0, -index).Format(DateFormat)
		}
		return forDays, nil
	} else {
		return nil, errors.New("不符合指定格式：" + DateFormat + "的日期")
	}
}

// 取两个日期之间的天数
func GetDaysCountBetween(startDate, endDate string) (int, error) {
	if ValidDateStr(startDate, DateFormat) && ValidDateStr(endDate, DateFormat) {
		loc, _ := time.LoadLocation("Local") //重要：获取时区
		st, _ := time.ParseInLocation(DateFormat, startDate, loc)
		et, _ := time.ParseInLocation(DateFormat, endDate, loc)
		days := int(et.UTC().Truncate(24*time.Hour).Sub(st.UTC().Truncate(24*time.Hour)).Hours() / 24)
		return days, nil
	} else {
		return 0, errors.New("不符合指定格式：" + DateFormat + "的日期")
	}
}

// 获取指定月份间的所有天数
func GetDaysOfMon(year, month int) int {
	if month == 4 || month == 6 || month == 9 || month == 11 {
		return 30

	} else if month != 2 {
		return 31
	} else {
		// 计算二月天数
		if ((year%4) == 0 && (year%100) != 0) || (year%400) == 0 {
			return 29
		} else {
			return 28
		}
	}
}

// 获取星期几
func GetWeekOfDay(dayStr, format string) (int, error) {
	if !ValidDateStr(dayStr, format) {
		return -1, errors.New("无效的日期")
	}
	loc, _ := time.LoadLocation("Local") //重要：获取时区
	day, _ := time.ParseInLocation(DateFormat, dayStr, loc)
	dayStr = day.Weekday().String()
	return WeekDict[dayStr], nil
}

//  获取从今天向前推 N 天的日期
func PreDayFromNowDay(N int) string {
	return time.Now().AddDate(0, 0, -N).Format(DateFormat)
}

//  获取从今天向前推 N 个月的日期
func PreMonthFromNowDay(N int) string {
	return time.Now().AddDate(0, -N, 0).Format(DateFormat)
}

//  获取从今天向前推 N 年的日期
func PreYearFromNowDay(N int) string {
	return time.Now().AddDate(-N, 0, 0).Format(DateFormat)
}

//  获取从指定日期向前推 N 个天的日期
func PreDayFromDay(N int, fromDate, format string) (string, error) {
	if !ValidDateStr(fromDate, format) {
		return "", errors.New("无效的日期")
	}
	loc, _ := time.LoadLocation("Local") //重要：获取时区
	dayTime, _ := time.ParseInLocation(DateFormat, fromDate, loc)
	return dayTime.AddDate(0, 0, -N).Format(DateFormat), nil
}

//  获取从指定日期向前推 N 个月
func PreDayFromMonth(N int, fromDate, format string) (string, error) {
	if !ValidDateStr(fromDate, format) {
		return "", errors.New("无效的日期")
	}
	loc, _ := time.LoadLocation("Local") //重要：获取时区
	dayTime, _ := time.ParseInLocation(DateFormat, fromDate, loc)
	return dayTime.AddDate(0, -N, 0).Format(DateFormat), nil
}

//  获取从指定日期向前推 N 年
func PreDayFromYear(N int, fromDate, format string) (string, error) {
	if !ValidDateStr(fromDate, format) {
		return "", errors.New("无效的日期")
	}
	loc, _ := time.LoadLocation("Local") //重要：获取时区
	dayTime, _ := time.ParseInLocation(DateFormat, fromDate, loc)
	return dayTime.AddDate(-N, 0, 0).Format(DateFormat), nil
}

// 下划线转驼峰
//  underStr 传入的待转换的字符串
//
func UnderToCam(underStr string) string {
	flag := false
	rs := []rune(underStr)
	var buf bytes.Buffer
	buf.Grow(len(rs))
	for _, v := range rs {
		if v == []rune("_")[0] {
			flag = true
			continue
		}
		if flag {
			buf.WriteString(strings.ToUpper(string(v)))
			flag = false
		} else {
			buf.WriteString(string(v))
		}
		flag = false
	}
	return buf.String()
}

// 截取字符串
//	str 传入要截取的字符串
//	start 起始位置
//	end 结束位置
func SubString(str string, start int, end int) string {
	rs := []rune(str)
	length := len(rs)

	if start < 0 || start > length {
		return ""
	}

	if end < 0 || end > length {
		return ""
	}
	//Output:
	//1 + 2 =3
	return string(rs[start:end])
}

// GUID  产生32位 GUID
func GUID() string {
	b := make([]byte, 48)

	if _, err := io.ReadFull(rand.Reader, b); err != nil {
		return ""
	}
	h := md5.New()
	h.Write([]byte(base64.URLEncoding.EncodeToString(b)))
	return hex.EncodeToString(h.Sum(nil))

}
